#include <uapi/linux/loop.h>
#include <linux/blk-mq.h>

struct loop_device {
    int     lo_number;
    loff_t      lo_offset;
    loff_t      lo_sizelimit;
    int     lo_flags;
    char        lo_file_name[LO_NAME_SIZE];

    struct file *   lo_backing_file;
    struct block_device *lo_device;

    gfp_t       old_gfp_mask;

    spinlock_t      lo_lock;
    int         lo_state;
    spinlock_t              lo_work_lock;
    struct workqueue_struct *workqueue;
    struct work_struct      rootcg_work;
    struct list_head        rootcg_cmd_list;
    struct list_head        idle_worker_list;
    struct rb_root          worker_tree;
    struct timer_list       timer;
    bool            use_dio;
    bool            sysfs_inited;
    
    struct request_queue    *lo_queue;
    struct blk_mq_tag_set   tag_set;
    struct gendisk      *lo_disk;
    struct mutex        lo_mutex;
    bool            idr_visible;
};

struct loop_cmd {
    struct list_head list_entry;
    bool use_aio; /* use AIO interface to handle I/O */
    atomic_t ref; /* only for aio */
    long ret;
    struct kiocb iocb;
    struct bio_vec *bvec;
    struct cgroup_subsys_state *blkcg_css;
    struct cgroup_subsys_state *memcg_css;
};

struct bdev_inode {
    struct block_device bdev;
    struct inode vfs_inode;
};
static inline struct bdev_inode *BDEV_I(struct inode *inode)
{
    return container_of(inode, struct bdev_inode, vfs_inode);
}

static struct block_device *I_BDEV_FTRACE(struct inode *inode)
{
    return &BDEV_I(inode)->bdev;
}
